#!/usr/bin/python2.4

# pylint: disable-msg=C6304

"""Tests vector fields."""

import string
import StringIO
import sys
import unittest

from matrix import DM
from matrix import LatLon
from matrix import Polar
import timeformat
from vectorfield import CoordsToVector
from vectorfield import VectorField


def Compress(astr):
  return string.replace(astr, ' ', '')


class TestVectorField(unittest.TestCase):

  def testSinglePoint(self):
    t0 = 1*3600
    ll0 = LatLon(DM(48, 0), -DM(125, 0))
    ll1 = LatLon(DM(48, 10), -DM(125, 0))
    p0 = Polar(1000.0, 0.0)
    c0 = CoordsToVector(t0, ll0, p0)  # use same time
    vf = VectorField('test')
    vf.SetLatLonFuzzMinutes(50, 50)
    vf._ReadFromFileHandle(StringIO.StringIO(c0.CSVFormat()))
    self.assertEqual(p0, vf.Index(t0, ll0))  # expect direct hit
    self.assertEqual(p0, vf.Index(t0+1000, ll0))  # only one point in field
    self.assertEqual(p0, vf.Index(t0, ll1))  # only one point in field
    self.assertEqual(p0, vf.Index(t0+1000, ll1))  # only one point in field

  def testMidLatitude(self):
    t0 = 1*3600
    t1 = t0
    ll0 = LatLon(DM(48, 0), -DM(125, 0))
    # llm = LatLon(DM(48, 5), -DM(125, 0))
    ll1 = LatLon(DM(48, 10), -DM(125, 0))  # 10 minutes north of ll0
    p0 = Polar(1000.0, 0.0)
    p1 = Polar(2000.0, 0.0)
    c0 = CoordsToVector(t0, ll0, p0)
    c1 = CoordsToVector(t1, ll1, p1)
    vf = VectorField('test')
    vf._ReadFromFileHandle(StringIO.StringIO(
        '\n'.join([c0.CSVFormat(), c1.CSVFormat()])))
    self.assertEqual(p0, vf.Index(t0, ll0))  # expect direct hit
    self.assertEqual(p1, vf.Index(t1, ll1))  # expect direct hit
    # XXX TODO(rrh): this doesn't deliver what's expected
    # self.assertEqual(Polar(1500, 0.0), vf.Index(t0, llm))

  def testMidTime(self):
    t0 = 1*3600
    tm = 1*1800-1
    t1 = 2*3600
    ll0 = LatLon(DM(48, 0), -DM(125, 0))
    ll1 = LatLon(DM(48, 0), -DM(125, 0))
    p0 = Polar(1000.0, 0.0)
    p1 = Polar(2000.0, 0.0)
    c0 = CoordsToVector(t0, ll0, p0)
    c1 = CoordsToVector(t1, ll1, p1)
    vf = VectorField('test')
    vf._ReadFromFileHandle(StringIO.StringIO(
        '\n'.join([c0.CSVFormat(), c1.CSVFormat()])))
    self.assertEqual(p0, vf.Index(t0, ll0))  # expect direct hit
    self.assertEqual(p1, vf.Index(t1, ll1))  # expect direct hit

    # XXX TODO(rrh): this doesn't deliver what's expected?!
    trace = False
    value = vf.Index(tm, ll1, trace)
    if trace:
      print 'value=%s' % (value)
    # self.assertEqual(Polar(1500, 0.0), value)


class TestCoordsToVector(unittest.TestCase):

  def testAll(self):  # TODO(rrh): DO NOT COMMIT with Ignored prefix
    t0 = timeformat.ScanTimeString('2011-05-03 1603')
    # t1 = t0 + 100

    ll = LatLon(DM(48, 0), -DM(125, 0))
    p = Polar(1000.0, 0.0)
    c = CoordsToVector(t0, ll, p)
    self.assertEqual(t0, c.GetTime())
    self.assertEqual(ll, c.GetLatLon())
    self.assertEqual(p, c.GetValue())
    self.assertEqual(
        Compress(
            ('CoordsToVector(%d,LatLon(DM(48,0),-DM(125,0)),'
             'Polar(1000.00,000),attribution=None)') % t0),
        Compress(str(c)))
    self.assertEqual(
        Compress(
            ('CoordsToVector(%d {2011-05-03 1603},'
             'LatLon(DM(48,0),-DM(125,0)),Polar(1000.00,000),None)') % t0),
        Compress(c.FormatVerbose()))
    self.assertEqual(
        Compress('%d,1,048,00,-1,125,00,1000.00,000,"None"' % t0),
        Compress(c.CSVFormat()))
    self.assertEqual(
        (c, 9),
        CoordsToVector.BuildFromCSV(
            [17, t0, 1, 48, 0, -1, 125, 0, 1000, 0, 'None'],
            1))

  def testGrid(self):
    trace = False
    t0 = timeformat.ScanTimeString('2011-05-03 1603')
    vf = VectorField('test-vf')
    for dlat in xrange(-2, 2+1):
      for dlon in xrange(-2, 2+1):
        ll = LatLon(DM(48, 30 + dlat), -DM(124, 30 + dlon))
        cv = CoordsToVector(
            t0,
            ll,
            Polar(dlat * 10 + dlon, 0),
            attribution=str(ll))
        vf.AddItem(cv)
    vf.BuildModelFromAllData()
    vf.SetLatLonFuzzMinutes(60, 60)
    if False:
      vf.Print(sys.stdout)

    # Look outside the given grid, and expect to get mapped to the nearest
    # point, which will be on grid lines.
    # Do this for being S, N, W and E of the grid.
    for dlat in xrange(-10, -8):  # S
      dlon = 0
      ll = LatLon(DM(48, 30 + dlat), -DM(124, 30 + dlon))
      p = vf.Index(t0, ll, trace=trace)
      self.assertEqual(Polar(-2 * 10 + dlon, 0), p)

    for dlat in xrange(8, 10):  # N
      dlon = 0
      ll = LatLon(DM(48, 30 + dlat), -DM(124, 30 + dlon))
      p = vf.Index(t0, ll, trace=trace)
      self.assertEqual(Polar(2 * 10 + dlon, 0), p)

    for dlon in xrange(-10, -8):  # W
      dlat = 0
      ll = LatLon(DM(48, 30 + dlat), -DM(124, 30 + dlon))
      p = vf.Index(t0, ll, trace=trace)
      self.assertEqual(Polar(0 + -2, 0), p)

    for dlon in xrange(8, 10):  # E
      dlat = 0
      ll = LatLon(DM(48, 30 + dlat), -DM(124, 30 + dlon))
      p = vf.Index(t0, ll, trace=trace)
      self.assertEqual(Polar(0 + 2, 0), p)


def main():
  unittest.main()


if __name__ == '__main__':
  main()
